package com.kenai.jbosh;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

public final class BOSHClient
{
  private static final boolean ASSERTIONS = 0;
  private static final int DEFAULT_EMPTY_REQUEST_DELAY = 100;
  private static final int DEFAULT_PAUSE_MARGIN = 500;
  private static final int EMPTY_REQUEST_DELAY = 0;
  private static final String ERROR = "error";
  private static final String INTERRUPTED = "Interrupted";
  private static final Logger LOG;
  private static final String NULL_LISTENER = "Listener may not be null";
  private static final int PAUSE_MARGIN = 0;
  private static final String TERMINATE = "terminate";
  private static final String UNHANDLED = "Unhandled Exception";
  private final BOSHClientConfig cfg;
  private CMSessionParams cmParams;
  private final Set<BOSHClientConnListener> connListeners = new CopyOnWriteArraySet();
  private final Condition drained;
  private ScheduledFuture emptyRequestFuture;
  private final Runnable emptyRequestRunnable;
  private final AtomicReference<ExchangeInterceptor> exchInterceptor;
  private Queue<HTTPExchange> exchanges;
  private final HTTPSender httpSender;
  private final ReentrantLock lock;
  private final Condition notEmpty;
  private final Condition notFull;
  private List<ComposableBody> pendingRequestAcks;
  private SortedSet<Long> pendingResponseAcks;
  private final Runnable procRunnable;
  private Thread procThread;
  private final RequestIDSequence requestIDSeq;
  private final Set<BOSHClientRequestListener> requestListeners = new CopyOnWriteArraySet();
  private Long responseAck;
  private final Set<BOSHClientResponseListener> responseListeners = new CopyOnWriteArraySet();
  private final ScheduledExecutorService schedExec;

  static
  {
    int i;
    String str;
    if (!(BOSHClient.class.desiredAssertionStatus()))
      i = 1;
    while (true)
    {
      $assertionsDisabled = i;
      LOG = Logger.getLogger(BOSHClient.class.getName());
      EMPTY_REQUEST_DELAY = Integer.getInteger(BOSHClient.class.getName() + ".emptyRequestDelay", 100).intValue();
      PAUSE_MARGIN = Integer.getInteger(BOSHClient.class.getName() + ".pauseMargin", 500).intValue();
      str = BOSHClient.class.getSimpleName() + ".assertionsEnabled";
      bool = false;
      if (System.getProperty(str) != null)
        break;
      if ($assertionsDisabled)
        break label157;
      bool = true;
      if (bool)
        break label157;
      throw new AssertionError();
      i = 0;
    }
    boolean bool = Boolean.getBoolean(str);
    label157: ASSERTIONS = bool;
  }

  private BOSHClient(BOSHClientConfig paramBOSHClientConfig)
  {
    this.lock = new ReentrantLock();
    this.notEmpty = this.lock.newCondition();
    this.notFull = this.lock.newCondition();
    this.drained = this.lock.newCondition();
    this.procRunnable = new Runnable(this)
    {
      public void run()
      {
        BOSHClient.access$0(this.this$0);
      }
    };
    this.emptyRequestRunnable = new Runnable(this)
    {
      public void run()
      {
        BOSHClient.access$1(this.this$0);
      }
    };
    this.httpSender = new ApacheHTTPSender();
    this.exchInterceptor = new AtomicReference();
    this.requestIDSeq = new RequestIDSequence();
    this.schedExec = Executors.newSingleThreadScheduledExecutor();
    this.exchanges = new LinkedList();
    this.pendingResponseAcks = new TreeSet();
    this.responseAck = Long.valueOf(-1L);
    this.pendingRequestAcks = new ArrayList();
    this.cfg = paramBOSHClientConfig;
    init();
  }

  private void applyFrom(ComposableBody.Builder paramBuilder)
  {
    assertLocked();
    String str = this.cfg.getFrom();
    if (str != null)
      paramBuilder.setAttribute(Attributes.FROM, str);
  }

  private void applyResponseAcknowledgement(ComposableBody.Builder paramBuilder, long paramLong)
  {
    assertLocked();
    if (this.responseAck.equals(Long.valueOf(-1L)));
    while (true)
    {
      Long localLong;
      do
      {
        return;
        localLong = Long.valueOf(paramLong - 1L);
      }
      while (this.responseAck.equals(localLong));
      paramBuilder.setAttribute(Attributes.ACK, this.responseAck.toString());
    }
  }

  private void applyRoute(ComposableBody.Builder paramBuilder)
  {
    assertLocked();
    String str = this.cfg.getRoute();
    if (str != null)
      paramBuilder.setAttribute(Attributes.ROUTE, str);
  }

  private ComposableBody applySessionCreationRequest(long paramLong, ComposableBody paramComposableBody)
    throws BOSHException
  {
    assertLocked();
    ComposableBody.Builder localBuilder = paramComposableBody.rebuild();
    localBuilder.setAttribute(Attributes.TO, this.cfg.getTo());
    localBuilder.setAttribute(Attributes.XML_LANG, this.cfg.getLang());
    localBuilder.setAttribute(Attributes.VER, AttrVersion.getSupportedVersion().toString());
    localBuilder.setAttribute(Attributes.WAIT, "60");
    localBuilder.setAttribute(Attributes.HOLD, "1");
    localBuilder.setAttribute(Attributes.RID, Long.toString(paramLong));
    applyRoute(localBuilder);
    applyFrom(localBuilder);
    localBuilder.setAttribute(Attributes.ACK, "1");
    localBuilder.setAttribute(Attributes.SID, null);
    return localBuilder.build();
  }

  private ComposableBody applySessionData(long paramLong, ComposableBody paramComposableBody)
    throws BOSHException
  {
    assertLocked();
    ComposableBody.Builder localBuilder = paramComposableBody.rebuild();
    localBuilder.setAttribute(Attributes.SID, this.cmParams.getSessionID().toString());
    localBuilder.setAttribute(Attributes.RID, Long.toString(paramLong));
    applyResponseAcknowledgement(localBuilder, paramLong);
    return localBuilder.build();
  }

  private void assertLocked()
  {
    if ((ASSERTIONS) && (!(this.lock.isHeldByCurrentThread())))
      throw new AssertionError("Lock is not held by current thread");
  }

  private void assertUnlocked()
  {
    if ((ASSERTIONS) && (this.lock.isHeldByCurrentThread()))
      throw new AssertionError("Lock is held by current thread");
  }

  private void blockUntilSendable(AbstractBody paramAbstractBody)
  {
    assertLocked();
    if ((!(isWorking())) || (isImmediatelySendable(paramAbstractBody)))
      return;
    try
    {
      this.notFull.await();
    }
    catch (InterruptedException localInterruptedException)
    {
      LOG.log(Level.FINEST, "Interrupted", localInterruptedException);
    }
  }

  private void checkForTerminalBindingConditions(AbstractBody paramAbstractBody, int paramInt)
    throws BOSHException
  {
    TerminalBindingCondition localTerminalBindingCondition = getTerminalBindingCondition(paramInt, paramAbstractBody);
    if (localTerminalBindingCondition != null)
      throw new BOSHException("Terminal binding condition encountered: " + localTerminalBindingCondition.getCondition() + "  (" + localTerminalBindingCondition.getMessage() + ")");
  }

  private void clearEmptyRequest()
  {
    assertLocked();
    if (this.emptyRequestFuture != null)
    {
      this.emptyRequestFuture.cancel(false);
      this.emptyRequestFuture = null;
    }
  }

  public static BOSHClient create(BOSHClientConfig paramBOSHClientConfig)
  {
    if (paramBOSHClientConfig == null)
      throw new IllegalArgumentException("Client configuration may not be null");
    return new BOSHClient(paramBOSHClientConfig);
  }

  // ERROR //
  private void dispose(Throwable paramThrowable)
  {
    // Byte code:
    //   0: aload_0
    //   1: invokespecial 452	com/kenai/jbosh/BOSHClient:assertUnlocked	()V
    //   4: aload_0
    //   5: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   8: invokevirtual 454	java/util/concurrent/locks/ReentrantLock:lock	()V
    //   11: aload_0
    //   12: getfield 456	com/kenai/jbosh/BOSHClient:procThread	Ljava/lang/Thread;
    //   15: astore_3
    //   16: aload_3
    //   17: ifnonnull +11 -> 28
    //   20: aload_0
    //   21: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   24: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   27: return
    //   28: aload_0
    //   29: aconst_null
    //   30: putfield 456	com/kenai/jbosh/BOSHClient:procThread	Ljava/lang/Thread;
    //   33: aload_0
    //   34: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   37: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   40: aload_1
    //   41: ifnonnull +104 -> 145
    //   44: aload_0
    //   45: invokespecial 462	com/kenai/jbosh/BOSHClient:fireConnectionClosed	()V
    //   48: aload_0
    //   49: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   52: invokevirtual 454	java/util/concurrent/locks/ReentrantLock:lock	()V
    //   55: aload_0
    //   56: invokespecial 464	com/kenai/jbosh/BOSHClient:clearEmptyRequest	()V
    //   59: aload_0
    //   60: aconst_null
    //   61: putfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   64: aload_0
    //   65: aconst_null
    //   66: putfield 361	com/kenai/jbosh/BOSHClient:cmParams	Lcom/kenai/jbosh/CMSessionParams;
    //   69: aload_0
    //   70: aconst_null
    //   71: putfield 233	com/kenai/jbosh/BOSHClient:pendingResponseAcks	Ljava/util/SortedSet;
    //   74: aload_0
    //   75: aconst_null
    //   76: putfield 247	com/kenai/jbosh/BOSHClient:pendingRequestAcks	Ljava/util/List;
    //   79: aload_0
    //   80: getfield 188	com/kenai/jbosh/BOSHClient:notEmpty	Ljava/util/concurrent/locks/Condition;
    //   83: invokeinterface 467 1 0
    //   88: aload_0
    //   89: getfield 190	com/kenai/jbosh/BOSHClient:notFull	Ljava/util/concurrent/locks/Condition;
    //   92: invokeinterface 467 1 0
    //   97: aload_0
    //   98: getfield 192	com/kenai/jbosh/BOSHClient:drained	Ljava/util/concurrent/locks/Condition;
    //   101: invokeinterface 467 1 0
    //   106: aload_0
    //   107: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   110: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   113: aload_0
    //   114: getfield 205	com/kenai/jbosh/BOSHClient:httpSender	Lcom/kenai/jbosh/HTTPSender;
    //   117: invokeinterface 472 1 0
    //   122: aload_0
    //   123: getfield 223	com/kenai/jbosh/BOSHClient:schedExec	Ljava/util/concurrent/ScheduledExecutorService;
    //   126: invokeinterface 478 1 0
    //   131: pop
    //   132: goto -105 -> 27
    //   135: astore_2
    //   136: aload_0
    //   137: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   140: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   143: aload_2
    //   144: athrow
    //   145: aload_0
    //   146: aload_1
    //   147: invokespecial 481	com/kenai/jbosh/BOSHClient:fireConnectionClosedOnError	(Ljava/lang/Throwable;)V
    //   150: goto -102 -> 48
    //   153: astore 4
    //   155: aload_0
    //   156: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   159: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   162: aload 4
    //   164: athrow
    //
    // Exception table:
    //   from	to	target	type
    //   11	16	135	finally
    //   28	33	135	finally
    //   55	106	153	finally
  }

  private void fireConnectionClosed()
  {
    assertUnlocked();
    BOSHClientConnEvent localBOSHClientConnEvent = null;
    Iterator localIterator = this.connListeners.iterator();
    if (!(localIterator.hasNext()))
      return;
    BOSHClientConnListener localBOSHClientConnListener = (BOSHClientConnListener)localIterator.next();
    if (localBOSHClientConnEvent == null)
      localBOSHClientConnEvent = BOSHClientConnEvent.createConnectionClosedEvent(this);
    try
    {
      localBOSHClientConnListener.connectionEvent(localBOSHClientConnEvent);
    }
    catch (Exception localException)
    {
      LOG.log(Level.WARNING, "Unhandled Exception", localException);
    }
  }

  private void fireConnectionClosedOnError(Throwable paramThrowable)
  {
    assertUnlocked();
    BOSHClientConnEvent localBOSHClientConnEvent = null;
    Iterator localIterator = this.connListeners.iterator();
    if (!(localIterator.hasNext()))
      return;
    BOSHClientConnListener localBOSHClientConnListener = (BOSHClientConnListener)localIterator.next();
    if (localBOSHClientConnEvent == null)
      localBOSHClientConnEvent = BOSHClientConnEvent.createConnectionClosedOnErrorEvent(this, this.pendingRequestAcks, paramThrowable);
    try
    {
      localBOSHClientConnListener.connectionEvent(localBOSHClientConnEvent);
    }
    catch (Exception localException)
    {
      LOG.log(Level.WARNING, "Unhandled Exception", localException);
    }
  }

  private void fireConnectionEstablished()
  {
    BOSHClientConnListener localBOSHClientConnListener;
    boolean bool1 = this.lock.isHeldByCurrentThread();
    if (bool1)
      this.lock.unlock();
    Object localObject1 = null;
    try
    {
      Iterator localIterator = this.connListeners.iterator();
      boolean bool2 = localIterator.hasNext();
      if (!(bool2))
      {
        if (bool1)
          this.lock.lock();
        return;
      }
      localBOSHClientConnListener = (BOSHClientConnListener)localIterator.next();
      if (localObject1 == null)
      {
        BOSHClientConnEvent localBOSHClientConnEvent;
        localObject1 = localBOSHClientConnEvent;
      }
    }
    finally
    {
      try
      {
        localBOSHClientConnListener.connectionEvent(localObject1);
      }
      catch (Exception localException)
      {
        while (true)
          LOG.log(Level.WARNING, "Unhandled Exception", localException);
        localObject2 = finally;
        if (bool1)
          this.lock.lock();
        throw localObject2;
      }
    }
  }

  private void fireRequestSent(AbstractBody paramAbstractBody)
  {
    assertUnlocked();
    BOSHMessageEvent localBOSHMessageEvent = null;
    Iterator localIterator = this.requestListeners.iterator();
    if (!(localIterator.hasNext()))
      return;
    BOSHClientRequestListener localBOSHClientRequestListener = (BOSHClientRequestListener)localIterator.next();
    if (localBOSHMessageEvent == null)
      localBOSHMessageEvent = BOSHMessageEvent.createRequestSentEvent(this, paramAbstractBody);
    try
    {
      localBOSHClientRequestListener.requestSent(localBOSHMessageEvent);
    }
    catch (Exception localException)
    {
      LOG.log(Level.WARNING, "Unhandled Exception", localException);
    }
  }

  private void fireResponseReceived(AbstractBody paramAbstractBody)
  {
    assertUnlocked();
    BOSHMessageEvent localBOSHMessageEvent = null;
    Iterator localIterator = this.responseListeners.iterator();
    if (!(localIterator.hasNext()))
      return;
    BOSHClientResponseListener localBOSHClientResponseListener = (BOSHClientResponseListener)localIterator.next();
    if (localBOSHMessageEvent == null)
      localBOSHMessageEvent = BOSHMessageEvent.createResponseReceivedEvent(this, paramAbstractBody);
    try
    {
      localBOSHClientResponseListener.responseReceived(localBOSHMessageEvent);
    }
    catch (Exception localException)
    {
      LOG.log(Level.WARNING, "Unhandled Exception", localException);
    }
  }

  private long getDefaultEmptyRequestDelay()
  {
    long l;
    assertLocked();
    AttrPolling localAttrPolling = this.cmParams.getPollingInterval();
    if (localAttrPolling == null)
      l = EMPTY_REQUEST_DELAY;
    while (true)
    {
      return l;
      l = localAttrPolling.getInMilliseconds();
    }
  }

  private TerminalBindingCondition getTerminalBindingCondition(int paramInt, AbstractBody paramAbstractBody)
  {
    TerminalBindingCondition localTerminalBindingCondition;
    assertLocked();
    if (isTermination(paramAbstractBody))
      localTerminalBindingCondition = TerminalBindingCondition.forString(paramAbstractBody.getAttribute(Attributes.CONDITION));
    while (true)
    {
      while (true)
      {
        return localTerminalBindingCondition;
        if ((this.cmParams == null) || (this.cmParams.getVersion() != null))
          break;
        localTerminalBindingCondition = TerminalBindingCondition.forHTTPResponseCode(paramInt);
      }
      localTerminalBindingCondition = null;
    }
  }

  private void init()
  {
    assertUnlocked();
    this.lock.lock();
    try
    {
      this.httpSender.init(this.cfg);
      this.procThread = new Thread(this.procRunnable);
      this.procThread.setDaemon(true);
      this.procThread.setName(BOSHClient.class.getSimpleName() + "[" + System.identityHashCode(this) + "]: Receive thread");
      this.procThread.start();
      return;
    }
    finally
    {
      this.lock.unlock();
    }
  }

  private boolean isImmediatelySendable(AbstractBody paramAbstractBody)
  {
    boolean bool;
    assertLocked();
    if (this.cmParams == null)
      bool = this.exchanges.isEmpty();
    while (true)
    {
      while (true)
      {
        int i;
        while (true)
        {
          AttrRequests localAttrRequests;
          while (true)
          {
            return bool;
            localAttrRequests = this.cmParams.getRequests();
            if (localAttrRequests != null)
              break;
            bool = true;
          }
          i = localAttrRequests.intValue();
          if (this.exchanges.size() >= i)
            break;
          bool = true;
        }
        if ((this.exchanges.size() != i) || ((!(isTermination(paramAbstractBody))) && (!(isPause(paramAbstractBody)))))
          break;
        bool = true;
      }
      bool = false;
    }
  }

  private static boolean isPause(AbstractBody paramAbstractBody)
  {
    int i;
    if (paramAbstractBody.getAttribute(Attributes.PAUSE) != null)
      i = 1;
    while (true)
    {
      return i;
      i = 0;
    }
  }

  private static boolean isRecoverableBindingCondition(AbstractBody paramAbstractBody)
  {
    return "error".equals(paramAbstractBody.getAttribute(Attributes.TYPE));
  }

  private static boolean isTermination(AbstractBody paramAbstractBody)
  {
    return "terminate".equals(paramAbstractBody.getAttribute(Attributes.TYPE));
  }

  private boolean isWorking()
  {
    int i;
    assertLocked();
    if (this.procThread != null)
      i = 1;
    while (true)
    {
      return i;
      i = 0;
    }
  }

  private HTTPExchange nextExchange()
  {
    assertUnlocked();
    Thread localThread = Thread.currentThread();
    HTTPExchange localHTTPExchange = null;
    this.lock.lock();
    try
    {
      boolean bool = localThread.equals(this.procThread);
      if (!(bool))
      {
        this.lock.unlock();
        return localHTTPExchange;
      }
      if (localHTTPExchange == null);
    }
    finally
    {
      try
      {
        do
          this.notEmpty.await();
        while (localHTTPExchange == null);
      }
      catch (InterruptedException localInterruptedException)
      {
        while (true)
          LOG.log(Level.FINEST, "Interrupted", localInterruptedException);
        localObject = finally;
        this.lock.unlock();
        throw localObject;
      }
    }
  }

  // ERROR //
  private void processExchange(HTTPExchange paramHTTPExchange)
  {
    // Byte code:
    //   0: aload_0
    //   1: invokespecial 452	com/kenai/jbosh/BOSHClient:assertUnlocked	()V
    //   4: aload_1
    //   5: invokevirtual 649	com/kenai/jbosh/HTTPExchange:getHTTPResponse	()Lcom/kenai/jbosh/HTTPResponse;
    //   8: astore 4
    //   10: aload 4
    //   12: invokeinterface 655 1 0
    //   17: astore 5
    //   19: aload 4
    //   21: invokeinterface 658 1 0
    //   26: istore 6
    //   28: aload_0
    //   29: aload 5
    //   31: invokespecial 660	com/kenai/jbosh/BOSHClient:fireResponseReceived	(Lcom/kenai/jbosh/AbstractBody;)V
    //   34: aload_1
    //   35: invokevirtual 663	com/kenai/jbosh/HTTPExchange:getRequest	()Lcom/kenai/jbosh/AbstractBody;
    //   38: astore 7
    //   40: aconst_null
    //   41: astore 8
    //   43: aload_0
    //   44: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   47: invokevirtual 454	java/util/concurrent/locks/ReentrantLock:lock	()V
    //   50: aload_0
    //   51: invokespecial 390	com/kenai/jbosh/BOSHClient:isWorking	()Z
    //   54: ifne +125 -> 179
    //   57: aload_0
    //   58: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   61: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   64: aload_0
    //   65: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   68: invokevirtual 375	java/util/concurrent/locks/ReentrantLock:isHeldByCurrentThread	()Z
    //   71: ifeq +52 -> 123
    //   74: aload_0
    //   75: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   78: aload_1
    //   79: invokeinterface 666 2 0
    //   84: pop
    //   85: aload_0
    //   86: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   89: invokeinterface 610 1 0
    //   94: ifeq +13 -> 107
    //   97: aload_0
    //   98: aload_0
    //   99: aload 7
    //   101: invokespecial 670	com/kenai/jbosh/BOSHClient:processPauseRequest	(Lcom/kenai/jbosh/AbstractBody;)J
    //   104: invokespecial 674	com/kenai/jbosh/BOSHClient:scheduleEmptyRequest	(J)V
    //   107: aload_0
    //   108: getfield 190	com/kenai/jbosh/BOSHClient:notFull	Ljava/util/concurrent/locks/Condition;
    //   111: invokeinterface 467 1 0
    //   116: aload_0
    //   117: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   120: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   123: return
    //   124: astore_3
    //   125: getstatic 106	com/kenai/jbosh/BOSHClient:LOG	Ljava/util/logging/Logger;
    //   128: getstatic 405	java/util/logging/Level:FINEST	Ljava/util/logging/Level;
    //   131: ldc_w 676
    //   134: aload_3
    //   135: invokevirtual 409	java/util/logging/Logger:log	(Ljava/util/logging/Level;Ljava/lang/String;Ljava/lang/Throwable;)V
    //   138: aload_0
    //   139: aload_3
    //   140: invokespecial 678	com/kenai/jbosh/BOSHClient:dispose	(Ljava/lang/Throwable;)V
    //   143: goto -20 -> 123
    //   146: astore_2
    //   147: getstatic 106	com/kenai/jbosh/BOSHClient:LOG	Ljava/util/logging/Logger;
    //   150: getstatic 405	java/util/logging/Level:FINEST	Ljava/util/logging/Level;
    //   153: ldc 28
    //   155: aload_2
    //   156: invokevirtual 409	java/util/logging/Logger:log	(Ljava/util/logging/Level;Ljava/lang/String;Ljava/lang/Throwable;)V
    //   159: aload_0
    //   160: aload_2
    //   161: invokespecial 678	com/kenai/jbosh/BOSHClient:dispose	(Ljava/lang/Throwable;)V
    //   164: goto -41 -> 123
    //   167: astore 38
    //   169: aload_0
    //   170: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   173: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   176: aload 38
    //   178: athrow
    //   179: aload_0
    //   180: getfield 361	com/kenai/jbosh/BOSHClient:cmParams	Lcom/kenai/jbosh/CMSessionParams;
    //   183: ifnonnull +18 -> 201
    //   186: aload_0
    //   187: aload 7
    //   189: aload 5
    //   191: invokestatic 682	com/kenai/jbosh/CMSessionParams:fromSessionInit	(Lcom/kenai/jbosh/AbstractBody;Lcom/kenai/jbosh/AbstractBody;)Lcom/kenai/jbosh/CMSessionParams;
    //   194: putfield 361	com/kenai/jbosh/BOSHClient:cmParams	Lcom/kenai/jbosh/CMSessionParams;
    //   197: aload_0
    //   198: invokespecial 684	com/kenai/jbosh/BOSHClient:fireConnectionEstablished	()V
    //   201: aload_0
    //   202: getfield 361	com/kenai/jbosh/BOSHClient:cmParams	Lcom/kenai/jbosh/CMSessionParams;
    //   205: astore 16
    //   207: aload_0
    //   208: aload 5
    //   210: iload 6
    //   212: invokespecial 686	com/kenai/jbosh/BOSHClient:checkForTerminalBindingConditions	(Lcom/kenai/jbosh/AbstractBody;I)V
    //   215: aload 5
    //   217: invokestatic 557	com/kenai/jbosh/BOSHClient:isTermination	(Lcom/kenai/jbosh/AbstractBody;)Z
    //   220: ifeq +89 -> 309
    //   223: aload_0
    //   224: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   227: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   230: aload_0
    //   231: aconst_null
    //   232: invokespecial 678	com/kenai/jbosh/BOSHClient:dispose	(Ljava/lang/Throwable;)V
    //   235: aload_0
    //   236: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   239: invokevirtual 375	java/util/concurrent/locks/ReentrantLock:isHeldByCurrentThread	()Z
    //   242: ifeq -119 -> 123
    //   245: aload_0
    //   246: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   249: aload_1
    //   250: invokeinterface 666 2 0
    //   255: pop
    //   256: aload_0
    //   257: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   260: invokeinterface 610 1 0
    //   265: ifeq +13 -> 278
    //   268: aload_0
    //   269: aload_0
    //   270: aload 7
    //   272: invokespecial 670	com/kenai/jbosh/BOSHClient:processPauseRequest	(Lcom/kenai/jbosh/AbstractBody;)J
    //   275: invokespecial 674	com/kenai/jbosh/BOSHClient:scheduleEmptyRequest	(J)V
    //   278: aload_0
    //   279: getfield 190	com/kenai/jbosh/BOSHClient:notFull	Ljava/util/concurrent/locks/Condition;
    //   282: invokeinterface 467 1 0
    //   287: aload_0
    //   288: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   291: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   294: goto -171 -> 123
    //   297: astore 36
    //   299: aload_0
    //   300: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   303: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   306: aload 36
    //   308: athrow
    //   309: aload 5
    //   311: invokestatic 688	com/kenai/jbosh/BOSHClient:isRecoverableBindingCondition	(Lcom/kenai/jbosh/AbstractBody;)Z
    //   314: ifeq +428 -> 742
    //   317: new 244	java/util/ArrayList
    //   320: dup
    //   321: aload_0
    //   322: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   325: invokeinterface 620 1 0
    //   330: invokespecial 691	java/util/ArrayList:<init>	(I)V
    //   333: astore 17
    //   335: aload_0
    //   336: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   339: invokeinterface 692 1 0
    //   344: astore 21
    //   346: aload 21
    //   348: invokeinterface 494 1 0
    //   353: ifne +158 -> 511
    //   356: aload 17
    //   358: invokeinterface 695 1 0
    //   363: astore 25
    //   365: aload 25
    //   367: invokeinterface 494 1 0
    //   372: istore 26
    //   374: iload 26
    //   376: ifne +272 -> 648
    //   379: aload 17
    //   381: astore 8
    //   383: aload_0
    //   384: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   387: invokevirtual 375	java/util/concurrent/locks/ReentrantLock:isHeldByCurrentThread	()Z
    //   390: ifeq +52 -> 442
    //   393: aload_0
    //   394: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   397: aload_1
    //   398: invokeinterface 666 2 0
    //   403: pop
    //   404: aload_0
    //   405: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   408: invokeinterface 610 1 0
    //   413: ifeq +13 -> 426
    //   416: aload_0
    //   417: aload_0
    //   418: aload 7
    //   420: invokespecial 670	com/kenai/jbosh/BOSHClient:processPauseRequest	(Lcom/kenai/jbosh/AbstractBody;)J
    //   423: invokespecial 674	com/kenai/jbosh/BOSHClient:scheduleEmptyRequest	(J)V
    //   426: aload_0
    //   427: getfield 190	com/kenai/jbosh/BOSHClient:notFull	Ljava/util/concurrent/locks/Condition;
    //   430: invokeinterface 467 1 0
    //   435: aload_0
    //   436: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   439: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   442: aload 8
    //   444: ifnull -321 -> 123
    //   447: aload 8
    //   449: invokeinterface 695 1 0
    //   454: astore 29
    //   456: aload 29
    //   458: invokeinterface 494 1 0
    //   463: ifeq -340 -> 123
    //   466: aload 29
    //   468: invokeinterface 498 1 0
    //   473: checkcast 643	com/kenai/jbosh/HTTPExchange
    //   476: astore 30
    //   478: aload 30
    //   480: aload_0
    //   481: getfield 205	com/kenai/jbosh/BOSHClient:httpSender	Lcom/kenai/jbosh/HTTPSender;
    //   484: aload 16
    //   486: aload 30
    //   488: invokevirtual 663	com/kenai/jbosh/HTTPExchange:getRequest	()Lcom/kenai/jbosh/AbstractBody;
    //   491: invokeinterface 699 3 0
    //   496: invokevirtual 703	com/kenai/jbosh/HTTPExchange:setHTTPResponse	(Lcom/kenai/jbosh/HTTPResponse;)V
    //   499: aload_0
    //   500: aload 30
    //   502: invokevirtual 663	com/kenai/jbosh/HTTPExchange:getRequest	()Lcom/kenai/jbosh/AbstractBody;
    //   505: invokespecial 705	com/kenai/jbosh/BOSHClient:fireRequestSent	(Lcom/kenai/jbosh/AbstractBody;)V
    //   508: goto -52 -> 456
    //   511: aload 21
    //   513: invokeinterface 498 1 0
    //   518: checkcast 643	com/kenai/jbosh/HTTPExchange
    //   521: astore 22
    //   523: new 643	com/kenai/jbosh/HTTPExchange
    //   526: dup
    //   527: aload 22
    //   529: invokevirtual 663	com/kenai/jbosh/HTTPExchange:getRequest	()Lcom/kenai/jbosh/AbstractBody;
    //   532: invokespecial 707	com/kenai/jbosh/HTTPExchange:<init>	(Lcom/kenai/jbosh/AbstractBody;)V
    //   535: astore 23
    //   537: aload 17
    //   539: aload 23
    //   541: invokeinterface 710 2 0
    //   546: pop
    //   547: goto -201 -> 346
    //   550: astore 19
    //   552: aload 19
    //   554: astore 10
    //   556: aload 17
    //   558: pop
    //   559: getstatic 106	com/kenai/jbosh/BOSHClient:LOG	Ljava/util/logging/Logger;
    //   562: getstatic 405	java/util/logging/Level:FINEST	Ljava/util/logging/Level;
    //   565: ldc_w 712
    //   568: aload 10
    //   570: invokevirtual 409	java/util/logging/Logger:log	(Ljava/util/logging/Level;Ljava/lang/String;Ljava/lang/Throwable;)V
    //   573: aload_0
    //   574: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   577: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   580: aload_0
    //   581: aload 10
    //   583: invokespecial 678	com/kenai/jbosh/BOSHClient:dispose	(Ljava/lang/Throwable;)V
    //   586: aload_0
    //   587: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   590: invokevirtual 375	java/util/concurrent/locks/ReentrantLock:isHeldByCurrentThread	()Z
    //   593: ifeq -470 -> 123
    //   596: aload_0
    //   597: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   600: aload_1
    //   601: invokeinterface 666 2 0
    //   606: pop
    //   607: aload_0
    //   608: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   611: invokeinterface 610 1 0
    //   616: ifeq +13 -> 629
    //   619: aload_0
    //   620: aload_0
    //   621: aload 7
    //   623: invokespecial 670	com/kenai/jbosh/BOSHClient:processPauseRequest	(Lcom/kenai/jbosh/AbstractBody;)J
    //   626: invokespecial 674	com/kenai/jbosh/BOSHClient:scheduleEmptyRequest	(J)V
    //   629: aload_0
    //   630: getfield 190	com/kenai/jbosh/BOSHClient:notFull	Ljava/util/concurrent/locks/Condition;
    //   633: invokeinterface 467 1 0
    //   638: aload_0
    //   639: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   642: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   645: goto -522 -> 123
    //   648: aload 25
    //   650: invokeinterface 498 1 0
    //   655: checkcast 643	com/kenai/jbosh/HTTPExchange
    //   658: astore 27
    //   660: aload_0
    //   661: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   664: aload 27
    //   666: invokeinterface 713 2 0
    //   671: pop
    //   672: goto -307 -> 365
    //   675: astore 11
    //   677: aload 17
    //   679: pop
    //   680: aload_0
    //   681: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   684: invokevirtual 375	java/util/concurrent/locks/ReentrantLock:isHeldByCurrentThread	()Z
    //   687: ifeq +52 -> 739
    //   690: aload_0
    //   691: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   694: aload_1
    //   695: invokeinterface 666 2 0
    //   700: pop
    //   701: aload_0
    //   702: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   705: invokeinterface 610 1 0
    //   710: ifeq +13 -> 723
    //   713: aload_0
    //   714: aload_0
    //   715: aload 7
    //   717: invokespecial 670	com/kenai/jbosh/BOSHClient:processPauseRequest	(Lcom/kenai/jbosh/AbstractBody;)J
    //   720: invokespecial 674	com/kenai/jbosh/BOSHClient:scheduleEmptyRequest	(J)V
    //   723: aload_0
    //   724: getfield 190	com/kenai/jbosh/BOSHClient:notFull	Ljava/util/concurrent/locks/Condition;
    //   727: invokeinterface 467 1 0
    //   732: aload_0
    //   733: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   736: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   739: aload 11
    //   741: athrow
    //   742: aload_0
    //   743: aload 7
    //   745: aload 5
    //   747: invokespecial 717	com/kenai/jbosh/BOSHClient:processRequestAcknowledgements	(Lcom/kenai/jbosh/AbstractBody;Lcom/kenai/jbosh/AbstractBody;)V
    //   750: aload_0
    //   751: aload 7
    //   753: invokespecial 720	com/kenai/jbosh/BOSHClient:processResponseAcknowledgementData	(Lcom/kenai/jbosh/AbstractBody;)V
    //   756: aload_0
    //   757: aload 5
    //   759: invokespecial 724	com/kenai/jbosh/BOSHClient:processResponseAcknowledgementReport	(Lcom/kenai/jbosh/AbstractBody;)Lcom/kenai/jbosh/HTTPExchange;
    //   762: astore 33
    //   764: aload 33
    //   766: ifnull -383 -> 383
    //   769: iconst_0
    //   770: ifne -387 -> 383
    //   773: new 244	java/util/ArrayList
    //   776: dup
    //   777: iconst_1
    //   778: invokespecial 691	java/util/ArrayList:<init>	(I)V
    //   781: astore 17
    //   783: aload 17
    //   785: aload 33
    //   787: invokeinterface 710 2 0
    //   792: pop
    //   793: aload_0
    //   794: getfield 228	com/kenai/jbosh/BOSHClient:exchanges	Ljava/util/Queue;
    //   797: aload 33
    //   799: invokeinterface 713 2 0
    //   804: pop
    //   805: aload 17
    //   807: astore 8
    //   809: goto -426 -> 383
    //   812: astore 14
    //   814: aload_0
    //   815: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   818: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   821: aload 14
    //   823: athrow
    //   824: astore 12
    //   826: aload_0
    //   827: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   830: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   833: aload 12
    //   835: athrow
    //   836: astore 31
    //   838: aload_0
    //   839: getfield 182	com/kenai/jbosh/BOSHClient:lock	Ljava/util/concurrent/locks/ReentrantLock;
    //   842: invokevirtual 459	java/util/concurrent/locks/ReentrantLock:unlock	()V
    //   845: aload 31
    //   847: athrow
    //   848: astore 11
    //   850: goto -170 -> 680
    //   853: astore 9
    //   855: aload 9
    //   857: astore 10
    //   859: goto -300 -> 559
    //
    // Exception table:
    //   from	to	target	type
    //   4	28	124	BOSHException
    //   4	28	146	java/lang/InterruptedException
    //   74	116	167	finally
    //   245	287	297	finally
    //   335	374	550	BOSHException
    //   511	547	550	BOSHException
    //   648	672	550	BOSHException
    //   783	805	550	BOSHException
    //   335	374	675	finally
    //   511	547	675	finally
    //   648	672	675	finally
    //   783	805	675	finally
    //   596	638	812	finally
    //   690	732	824	finally
    //   393	435	836	finally
    //   50	64	848	finally
    //   179	235	848	finally
    //   309	335	848	finally
    //   559	586	848	finally
    //   742	783	848	finally
    //   50	64	853	BOSHException
    //   179	235	853	BOSHException
    //   309	335	853	BOSHException
    //   742	783	853	BOSHException
  }

  private void processMessages()
  {
    Object localObject2;
    HTTPExchange localHTTPExchange2;
    LOG.log(Level.FINEST, "Processing thread starting");
    try
    {
      HTTPExchange localHTTPExchange1 = nextExchange();
      localObject2 = localHTTPExchange1;
      if (localObject2 == null)
      {
        LOG.log(Level.FINEST, "Processing thread exiting");
        return;
      }
      ExchangeInterceptor localExchangeInterceptor = (ExchangeInterceptor)this.exchInterceptor.get();
      if (localExchangeInterceptor != null)
      {
        localHTTPExchange2 = localExchangeInterceptor.interceptExchange((HTTPExchange)localObject2);
        if (localHTTPExchange2 != null)
          break label164;
        label164: this.lock.lock();
      }
    }
    finally
    {
      try
      {
        while (true)
        {
          this.exchanges.remove(localObject2);
          this.lock.unlock();
        }
        localObject1 = finally;
        LOG.log(Level.FINEST, "Processing thread exiting");
        throw localObject1;
      }
      finally
      {
        while (true)
        {
          this.lock.unlock();
          throw localObject3;
          processExchange((HTTPExchange)localObject2);
        }
        localObject2 = localHTTPExchange2;
      }
    }
  }

  private long processPauseRequest(AbstractBody paramAbstractBody)
  {
    long l1;
    assertLocked();
    if ((this.cmParams != null) && (this.cmParams.getMaxPause() != null));
    try
    {
      AttrPause localAttrPause = AttrPause.createFromString(paramAbstractBody.getAttribute(Attributes.PAUSE));
      if (localAttrPause != null)
      {
        long l2 = localAttrPause.getInMilliseconds() - PAUSE_MARGIN;
        if (l2 < 0L)
        {
          int i = EMPTY_REQUEST_DELAY;
          l2 = i;
        }
        l1 = l2;
        return l1;
      }
    }
    catch (BOSHException localBOSHException)
    {
      LOG.log(Level.FINEST, "Could not extract", localBOSHException);
      l1 = getDefaultEmptyRequestDelay();
    }
  }

  private void processRequestAcknowledgements(AbstractBody paramAbstractBody1, AbstractBody paramAbstractBody2)
  {
    Long localLong;
    assertLocked();
    if (!(this.cmParams.isAckingRequests()));
    do
      return;
    while (paramAbstractBody2.getAttribute(Attributes.REPORT) != null);
    String str = paramAbstractBody2.getAttribute(Attributes.ACK);
    if (str == null)
      localLong = Long.valueOf(Long.parseLong(paramAbstractBody1.getAttribute(Attributes.RID)));
    while (true)
    {
      if (LOG.isLoggable(Level.FINEST))
        LOG.finest("Removing pending acks up to: " + localLong);
      Iterator localIterator = this.pendingRequestAcks.iterator();
      while (true)
      {
        do
          if (!(localIterator.hasNext()));
        while (Long.valueOf(Long.parseLong(((AbstractBody)localIterator.next()).getAttribute(Attributes.RID))).compareTo(localLong) > 0);
        localIterator.remove();
      }
      localLong = Long.valueOf(Long.parseLong(str));
    }
  }

  private void processResponseAcknowledgementData(AbstractBody paramAbstractBody)
  {
    assertLocked();
    Long localLong1 = Long.valueOf(Long.parseLong(paramAbstractBody.getAttribute(Attributes.RID)));
    if (this.responseAck.equals(Long.valueOf(-1L)))
    {
      this.responseAck = localLong1;
      return;
    }
    this.pendingResponseAcks.add(localLong1);
    Long localLong2 = Long.valueOf(1L + this.responseAck.longValue());
    while (true)
    {
      if ((this.pendingResponseAcks.isEmpty()) || (!(localLong2.equals(this.pendingResponseAcks.first()))));
      this.responseAck = localLong2;
      this.pendingResponseAcks.remove(localLong2);
      localLong2 = Long.valueOf(1L + localLong2.longValue());
    }
  }

  private HTTPExchange processResponseAcknowledgementReport(AbstractBody paramAbstractBody)
    throws BOSHException
  {
    Object localObject2;
    assertLocked();
    String str = paramAbstractBody.getAttribute(Attributes.REPORT);
    if (str == null)
      localObject2 = null;
    while (true)
    {
      return localObject2;
      Long localLong1 = Long.valueOf(Long.parseLong(str));
      Long localLong2 = Long.valueOf(Long.parseLong(paramAbstractBody.getAttribute(Attributes.TIME)));
      if (LOG.isLoggable(Level.FINE))
        LOG.fine("Received report of missing request (RID=" + localLong1 + ", time=" + localLong2 + "ms)");
      Iterator localIterator = this.pendingRequestAcks.iterator();
      Object localObject1 = null;
      while (true)
      {
        AbstractBody localAbstractBody;
        do
        {
          if ((!(localIterator.hasNext())) || (localObject1 != null))
          {
            if (localObject1 != null)
              break label202;
            throw new BOSHException("Report of missing message with RID '" + str + "' but local copy of that request was not found");
          }
          localAbstractBody = (AbstractBody)localIterator.next();
        }
        while (!(localLong1.equals(Long.valueOf(Long.parseLong(localAbstractBody.getAttribute(Attributes.RID))))));
        localObject1 = localAbstractBody;
      }
      label202: HTTPExchange localHTTPExchange = new HTTPExchange(localObject1);
      this.exchanges.add(localHTTPExchange);
      this.notEmpty.signalAll();
      localObject2 = localHTTPExchange;
    }
  }

  private void scheduleEmptyRequest(long paramLong)
  {
    assertLocked();
    if (paramLong < 0L)
      throw new IllegalArgumentException("Empty request delay must be >= 0 (was: " + paramLong + ")");
    clearEmptyRequest();
    if (!(isWorking()))
      return;
    if (LOG.isLoggable(Level.FINER))
      LOG.finer("Scheduling empty request in " + paramLong + "ms");
    try
    {
      this.emptyRequestFuture = this.schedExec.schedule(this.emptyRequestRunnable, paramLong, TimeUnit.MILLISECONDS);
      this.drained.signalAll();
    }
    catch (RejectedExecutionException localRejectedExecutionException)
    {
      while (true)
        LOG.log(Level.FINEST, "Could not schedule empty request", localRejectedExecutionException);
    }
  }

  private void sendEmptyRequest()
  {
    assertUnlocked();
    LOG.finest("Sending empty request");
    try
    {
      send(ComposableBody.builder().build());
      return;
    }
    catch (BOSHException localBOSHException)
    {
      dispose(localBOSHException);
    }
  }

  public void addBOSHClientConnListener(BOSHClientConnListener paramBOSHClientConnListener)
  {
    if (paramBOSHClientConnListener == null)
      throw new IllegalArgumentException("Listener may not be null");
    this.connListeners.add(paramBOSHClientConnListener);
  }

  public void addBOSHClientRequestListener(BOSHClientRequestListener paramBOSHClientRequestListener)
  {
    if (paramBOSHClientRequestListener == null)
      throw new IllegalArgumentException("Listener may not be null");
    this.requestListeners.add(paramBOSHClientRequestListener);
  }

  public void addBOSHClientResponseListener(BOSHClientResponseListener paramBOSHClientResponseListener)
  {
    if (paramBOSHClientResponseListener == null)
      throw new IllegalArgumentException("Listener may not be null");
    this.responseListeners.add(paramBOSHClientResponseListener);
  }

  public void close()
  {
    dispose(new BOSHException("Session explicitly closed by caller"));
  }

  public void disconnect()
    throws BOSHException
  {
    disconnect(ComposableBody.builder().build());
  }

  public void disconnect(ComposableBody paramComposableBody)
    throws BOSHException
  {
    if (paramComposableBody == null)
      throw new IllegalArgumentException("Message body may not be null");
    ComposableBody.Builder localBuilder = paramComposableBody.rebuild();
    localBuilder.setAttribute(Attributes.TYPE, "terminate");
    send(localBuilder.build());
  }

  void drain()
  {
    this.lock.lock();
    try
    {
      LOG.finest("Waiting while draining...");
      if ((!(isWorking())) || ((this.emptyRequestFuture != null) && (!(this.emptyRequestFuture.isDone()))))
      {
        LOG.finest("Drained");
        return;
      }
    }
    finally
    {
      try
      {
        this.drained.await();
      }
      catch (InterruptedException localInterruptedException)
      {
        while (true)
          LOG.log(Level.FINEST, "Interrupted", localInterruptedException);
        localObject = finally;
        this.lock.unlock();
        throw localObject;
      }
    }
  }

  public BOSHClientConfig getBOSHClientConfig()
  {
    return this.cfg;
  }

  CMSessionParams getCMSessionParams()
  {
    this.lock.lock();
    try
    {
      CMSessionParams localCMSessionParams = this.cmParams;
      return localCMSessionParams;
    }
    finally
    {
      this.lock.unlock();
    }
  }

  public boolean pause()
  {
    AttrMaxPause localAttrMaxPause;
    int i;
    assertUnlocked();
    this.lock.lock();
    try
    {
      CMSessionParams localCMSessionParams = this.cmParams;
      if (localCMSessionParams == null)
      {
        this.lock.unlock();
        i = 0;
        return i;
      }
      localAttrMaxPause = this.cmParams.getMaxPause();
      this.lock.unlock();
    }
    finally
    {
      try
      {
        while (true)
        {
          send(ComposableBody.builder().setAttribute(Attributes.PAUSE, localAttrMaxPause.toString()).build());
          i = 1;
        }
        localObject = finally;
        this.lock.unlock();
        throw localObject;
      }
      catch (BOSHException localBOSHException)
      {
        LOG.log(Level.FINEST, "Could not send pause", localBOSHException);
      }
    }
  }

  public void removeBOSHClientConnListener(BOSHClientConnListener paramBOSHClientConnListener)
  {
    if (paramBOSHClientConnListener == null)
      throw new IllegalArgumentException("Listener may not be null");
    this.connListeners.remove(paramBOSHClientConnListener);
  }

  public void removeBOSHClientRequestListener(BOSHClientRequestListener paramBOSHClientRequestListener)
  {
    if (paramBOSHClientRequestListener == null)
      throw new IllegalArgumentException("Listener may not be null");
    this.requestListeners.remove(paramBOSHClientRequestListener);
  }

  public void removeBOSHClientResponseListener(BOSHClientResponseListener paramBOSHClientResponseListener)
  {
    if (paramBOSHClientResponseListener == null)
      throw new IllegalArgumentException("Listener may not be null");
    this.responseListeners.remove(paramBOSHClientResponseListener);
  }

  public void send(ComposableBody paramComposableBody)
    throws BOSHException
  {
    assertUnlocked();
    if (paramComposableBody == null)
      throw new IllegalArgumentException("Message body may not be null");
    this.lock.lock();
    try
    {
      throw new BOSHException("Cannot send message when session is closed");
    }
    finally
    {
      ComposableBody localComposableBody;
      this.lock.unlock();
      throw localObject;
      long l = this.requestIDSeq.getNextRID();
      CMSessionParams localCMSessionParams = this.cmParams;
      if ((localCMSessionParams == null) && (this.exchanges.isEmpty()))
        localComposableBody = applySessionCreationRequest(l, paramComposableBody);
      while (true)
      {
        do
        {
          HTTPExchange localHTTPExchange = new HTTPExchange(localComposableBody);
          this.exchanges.add(localHTTPExchange);
          this.notEmpty.signalAll();
          clearEmptyRequest();
          this.lock.unlock();
          AbstractBody localAbstractBody = localHTTPExchange.getRequest();
          localHTTPExchange.setHTTPResponse(this.httpSender.send(localCMSessionParams, localAbstractBody));
          fireRequestSent(localAbstractBody);
          return;
          localComposableBody = applySessionData(l, paramComposableBody);
        }
        while (!(this.cmParams.isAckingRequests()));
        this.pendingRequestAcks.add(localComposableBody);
      }
    }
  }

  void setExchangeInterceptor(ExchangeInterceptor paramExchangeInterceptor)
  {
    this.exchInterceptor.set(paramExchangeInterceptor);
  }

  static abstract class ExchangeInterceptor
  {
    abstract HTTPExchange interceptExchange(HTTPExchange paramHTTPExchange);
  }
}